#include <stdio.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "driver/gpio.h"
#include "driver/ledc.h"
#include "esp_log.h"

#define LED_GPIO GPIO_NUM_27
#define FULL_EV_BIT    BIT0     //定义满占空比事件位
#define EMPTY_EV_BIT   BIT1

/*变量、句柄*/
EventGroupHandle_t ledc_event_handle;

/*任务函数*/
void led_task(void* argument){
    int gpio_level = 0;
    while(1){
        gpio_level = gpio_level?0:1;
        gpio_set_level(LED_GPIO, gpio_level);
        vTaskDelay(pdMS_TO_TICKS(500));
    }
}

bool IRAM_ATTR ledc_finish_cb(const ledc_cb_param_t *param, void *user_arg){
    //从ledc_cb_register代码可见回调函数没在IRAM会在日志提醒；
    BaseType_t taskWaken;
    if(param->duty){    //哪传入了参数param?
        xEventGroupSetBitsFromISR(ledc_event_handle, FULL_EV_BIT, &taskWaken);
    }
    else{
        xEventGroupSetBitsFromISR(ledc_event_handle, EMPTY_EV_BIT, &taskWaken);
    }
    return taskWaken;//为什么要返回这个？
}

void led_breathe_task(void* argument){
    
    while(1){
        EventBits_t event = xEventGroupWaitBits(ledc_event_handle, FULL_EV_BIT|EMPTY_EV_BIT, pdTRUE, pdFALSE, portMAX_DELAY);
        if(event & FULL_EV_BIT){
            ledc_set_fade_with_time(LEDC_LOW_SPEED_MODE, LEDC_CHANNEL_0, 0, 2000);
            ledc_fade_start(LEDC_LOW_SPEED_MODE, LEDC_CHANNEL_0, LEDC_FADE_NO_WAIT);    
        }
        else if(event & EMPTY_EV_BIT){
            ledc_set_fade_with_time(LEDC_LOW_SPEED_MODE, LEDC_CHANNEL_0, 8191, 2000);
            ledc_fade_start(LEDC_LOW_SPEED_MODE, LEDC_CHANNEL_0, LEDC_FADE_NO_WAIT);
        }
        //再设置回调函数
        ledc_cbs_t cbs = {
            .fade_cb = ledc_finish_cb,//LEDC fade_end callback function
        };
        ledc_cb_register(LEDC_LOW_SPEED_MODE, LEDC_CHANNEL_0, &cbs, NULL);
    }
}
//当配置 LEDC 为渐变模式时，必须在 LEDC_DUTY_CHNG_END_HSCHn 或者LEDC_DUTY_CHNG_END_LSCHn 中断之后才可以进行第二次渐变配置



void app_main(void)
{
/*初始化配置*/
    //话说回来……gpio连时钟都不用配置……
    // gpio_config_t led_config = {
    //     .pin_bit_mask = (1<<LED_GPIO),//设置引脚；这是个位掩码
    //     .mode = GPIO_MODE_OUTPUT_OD,
    //     .pull_up_en = GPIO_PULLUP_DISABLE,
    //     .pull_down_en = GPIO_PULLDOWN_DISABLE,
    //     .intr_type = GPIO_INTR_DISABLE,
    // };
    // gpio_config(&led_config);

    ledc_timer_config_t ledc_timer = {
        .speed_mode = LEDC_LOW_SPEED_MODE,
        .timer_num = LEDC_TIMER_0,
        .clk_cfg = LEDC_AUTO_CLK,            //时钟源
        //.deconfigure = ,
        .duty_resolution = LEDC_TIMER_13_BIT,  //占空比精度
        .freq_hz = 5000,
    };
    ledc_timer_config(&ledc_timer);

    ledc_channel_config_t ledc_channel = {
        .channel = LEDC_CHANNEL_0,
        .duty = 0,
        .gpio_num = GPIO_NUM_27,
        .speed_mode = LEDC_LOW_SPEED_MODE,
        .timer_sel = LEDC_TIMER_0,
        .intr_type = LEDC_INTR_DISABLE,
    };
    ledc_channel_config(&ledc_channel);

    //设置渐变
    ledc_fade_func_install(0);  //?
    ledc_set_fade_with_time(LEDC_LOW_SPEED_MODE, LEDC_CHANNEL_0, 8191, 2000);
    ledc_fade_start(LEDC_LOW_SPEED_MODE, LEDC_CHANNEL_0, LEDC_FADE_NO_WAIT);

/*事件组、任务*/
    ledc_event_handle = xEventGroupCreate();

    ledc_cbs_t cbs = {
        .fade_cb = ledc_finish_cb,//LEDC fade_end callback function
    };
    ledc_cb_register(LEDC_LOW_SPEED_MODE, LEDC_CHANNEL_0, &cbs, NULL);//注册LEDC回调函数
    
    BaseType_t res = xTaskCreatePinnedToCore(&led_breathe_task, "led_breathe_task", 2048, NULL, 3, NULL, APP_CPU_NUM);
    if(res != pdPASS){
        ESP_LOGI("led", "create fail");
    }
}
